/*
 * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package top.continew.admin.auth.handler;

import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import jakarta.annotation.Priority;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import top.continew.admin.auth.AbstractLoginHandler;
import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.req.EmailLoginReq;
import top.continew.admin.auth.model.req.WechatLoginReq;
import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.auth.service.WechatMiniAppService;
import top.continew.admin.common.config.properties.WxMaProperties;
import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.common.enums.GenderEnum;
import top.continew.admin.system.model.entity.user.UserDO;
import top.continew.admin.system.model.resp.ClientResp;
import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.validation.ValidationUtils;

import java.time.LocalDateTime;
import java.util.Random;

/**
 * 邮箱登录处理器
 *
 * @author KAI
 * @author Charles7c
 * @since 2024/12/22 14:58
 */
@Component
public class WechatLoginHandler extends AbstractLoginHandler<WechatLoginReq> {

    @Resource
    private WechatMiniAppService wechatMiniAppService;
    @Resource
    private WxMaProperties wxMaProperties;

    @Override
    public LoginResp login(WechatLoginReq req, ClientResp client, HttpServletRequest request) {
        // 验证微信登录
        WxMaProperties.Config config = wxMaProperties.getConfigs().get(0);
        WxMaJscode2SessionResult login = wechatMiniAppService.login(config.getAppid(), req.getCode());
        ValidationUtils.throwIfBlank(login.getOpenid(), "微信登录失败！");
        String openid = login.getOpenid();
        
        // 使用同步锁防止并发创建重复用户
        UserDO userDO = getOrCreateUser(openid);
        
        ValidationUtils.throwIfNull(userDO, "用户创建失败");
        // 检查用户状态
        super.checkUserStatus(userDO);
        // 执行认证
        String token = super.authenticate(userDO, client);
        return LoginResp.builder().token(token).build();
    }
    
    /**
     * 获取或创建用户（线程安全）
     */
    private synchronized UserDO getOrCreateUser(String openid) {
        // 再次查询，防止并发情况下重复创建
        UserDO userDO = userService.getOpenId(openid);
        if (userDO == null) {
            try {
                // 创建新用户
                userDO = new UserDO();
                userDO.setUsername("游客" + genStr());
                userDO.setNickname("游客");
                userDO.setPassword("Abcd@1234");
                userDO.setGender(GenderEnum.MALE);
                userDO.setOpenId(openid);
                userDO.setDescription("微信端注册用户");
                userDO.setStatus(DisEnableStatusEnum.ENABLE);
                userDO.setDeptId(547887852587843590L);
                userDO.setCreateTime(LocalDateTime.now());
                userService.save(userDO);
            } catch (Exception e) {
                // 如果保存失败（可能是唯一约束冲突），再次查询
                userDO = userService.getOpenId(openid);
                if (userDO == null) {
                    throw new RuntimeException("用户创建失败: " + e.getMessage(), e);
                }
            }
        }
        return userDO;
    }


    private String genStr() {
        Random random = new Random();
        StringBuilder sb = new StringBuilder(8);
        for (int i = 0; i < 8; i++) {
            int randomInt = random.nextInt(75) + 48; // 生成48到122之间的随机数，对应ASCII中的'0'-'z'
            sb.append((char) randomInt);
        }
        return sb.toString();
    }

    @Override
    public void preLogin(WechatLoginReq req, ClientResp client, HttpServletRequest request) {
        /*String email = req.getEmail();
        String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + email;
        String captcha = RedisUtils.get(captchaKey);
        ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED);
        ValidationUtils.throwIfNotEqualIgnoreCase(req.getCaptcha(), captcha, CAPTCHA_ERROR);
        RedisUtils.delete(captchaKey);*/
    }

    @Override
    public AuthTypeEnum getAuthType() {
        return AuthTypeEnum.WECHAT;
    }
}